﻿using System.Diagnostics;
using System.Windows.Forms;
using Outlook = Microsoft.Office.Interop.Outlook;
using Google.GData.Client;
using Google.GData.Calendar;
using System;
using System.Security.Cryptography;
using System.Text;
using Google.GData.Extensions;

namespace GoogleOutlookCalendarSync
	{
	public partial class Main : Form
		{
		public Main()
			{
			InitializeComponent();
#if true
			lvOutlookItems.Columns.Add( "Subject" );
			lvOutlookItems.Columns.Add( "Start" );
			lvOutlookItems.Columns.Add( "End" );
			lvOutlookItems.Columns.Add( "All Day" );
			lvOutlookItems.Columns.Add( "Recurrence" );
			lvOutlookItems.Columns.Add( "Recurrence Start" );
			lvOutlookItems.Columns.Add( "Recurrence End" );

#endif
			CalendarService service = new CalendarService( "gnc-GoogleOutlookCalendarSync-1" );
			string loginToken = getLoginToken();
			if ( loginToken != null )
				{
				service.SetAuthenticationToken( loginToken );
				}
			else
				{
				while ( loginToken == null )
					{
					using ( GoogleCredentialsDialog credentials = new GoogleCredentialsDialog() )
						{
						if ( credentials.ShowDialog() != System.Windows.Forms.DialogResult.OK )
							return;
						service.setUserCredentials( credentials.Username, credentials.Password );
						try
							{
							loginToken = service.QueryClientLoginToken();
							storeLoginToken( loginToken );
							}
						catch ( Exception ex )
							{
							MessageBox.Show( ex.Message );
							}
						}
					}
				}


#if false
			CalendarQuery query = new CalendarQuery();
			query.Uri = new Uri( "https://www.google.com/calendar/feeds/default/allcalendars/full" );
			CalendarFeed resultFeed = (CalendarFeed)gCalendar.Query( query );
			foreach ( CalendarEntry entry in resultFeed.Entries )
				Debug.WriteLine( entry.Title.Text );
#endif

			// http://www.google.com/calendar/feeds/23t20ush9bu3ksc0nh4u54bg2s%40group.calendar.google.com/private-d59f0ce1a6eaf3a09dabc8197e963d2e/full
			// https://www.google.com/calendar/feeds/default/owncalendars/full/23t20ush9bu3ksc0nh4u54bg2s@group.calendar.google.com
			// http://www.google.com/calendar/feeds/23t20ush9bu3ksc0nh4u54bg2s%40group.calendar.google.com/private/full

			lvGoogleItems.Columns.Add( "Subject" );
			lvGoogleItems.Columns.Add( "Start" );
			lvGoogleItems.Columns.Add( "End" );
			lvGoogleItems.Columns.Add( "All Day" );
			lvGoogleItems.Columns.Add( "Recurrence" );
			lvGoogleItems.Columns.Add( "Recurrence Start" );
			lvGoogleItems.Columns.Add( "Recurrence End" );

			string calendarUri = "http://www.google.com/calendar/feeds/23t20ush9bu3ksc0nh4u54bg2s%40group.calendar.google.com/private/full";
			EventQuery query = new EventQuery( calendarUri );
			query.SortOrder = CalendarSortOrder.descending;
			EventFeed feed;
			do
				{
				feed = service.Query( query );
				AtomFeed batchFeed = new AtomFeed( feed );
				foreach ( EventEntry entry in feed.Entries )
					{
					Debug.WriteLine( "Title: " + entry.Title.Text );

					ListViewItem lvi = new ListViewItem( new string[] { 
					entry.Title.Text,
					} );
					lvGoogleItems.Items.Add( lvi );

					if ( entry.Recurrence != null )
						Debug.WriteLine( "Recurrence: " + entry.Recurrence.Value );
					foreach ( Google.GData.Extensions.When when in entry.Times )
						{
						if ( when.AllDay )
							{
							lvi.SubItems.Add( "" );
							lvi.SubItems.Add( "" );
							}
						else
							{
							lvi.SubItems.Add( when.StartTime.ToString() );
							lvi.SubItems.Add( when.EndTime.ToString() );
							}
						lvi.SubItems.Add( when.AllDay.ToString() );
						Debug.WriteLine( when.StartTime + " - " + when.EndTime );
						}
					EventEntry toDelete = (EventEntry)entry;
					try
						{
						//toDelete.Delete();
						}
					catch ( Exception ex )
						{
						Debug.WriteLine( ex.Message );
						}
					toDelete.BatchData = new GDataBatchEntryData( entry.EventId, GDataBatchOperationType.delete );
					batchFeed.Entries.Add( toDelete );
					}

				EventFeed batchResultFeed = (EventFeed)service.Batch( batchFeed, new Uri( feed.Batch ) );
				foreach ( EventEntry entry in batchResultFeed.Entries )
					{
					if ( entry.BatchData.Status.Code != 200 && entry.BatchData.Status.Code != 201 )
						{
						Debug.WriteLine( "Failed: " + entry.BatchData.Id + ", status: " + entry.BatchData.Status.Code );
						}
					}
				}
			while ( feed.Entries.Count > 0 );




#if true
			Outlook.Application olApp = new Outlook.Application();
			Outlook.NameSpace olNS = olApp.GetNamespace( "mapi" );
			Outlook.MAPIFolder olCalendar = olNS.GetDefaultFolder( Outlook.OlDefaultFolders.olFolderCalendar );
			Outlook.Items olItems = olCalendar.Items;

			Outlook.AppointmentItem olAppt = (Outlook.AppointmentItem)olItems.GetFirst();
			while ( olAppt != null )
				{
				if ( olAppt.Start >= DateTime.Now )
					{
					Debug.WriteLine( "Subject: " + olAppt.Subject );
					Debug.WriteLine( "Organizer: " + olAppt.Organizer );
					Debug.WriteLine( "Start: " + olAppt.Start.ToString() );
					Debug.WriteLine( "End: " + olAppt.End.ToString() );
					//Debug.WriteLine( "Location: " + olAppt.Location );
					Debug.WriteLine( "Recurring: " + olAppt.IsRecurring );
					Debug.WriteLine( "All Day: " + olAppt.AllDayEvent );
					//Debug.WriteLine( "BusyStatus: " + olAppt.BusyStatus );
					//Debug.WriteLine( "Duration: " + olAppt.Duration );
					//Debug.WriteLine( "RecurrenceState: " + olAppt.RecurrenceState );

					Outlook.RecurrencePattern recurrencePattern = olAppt.GetRecurrencePattern();
					Debug.WriteLine( " RecurrenceType: " + recurrencePattern.RecurrenceType );
					Debug.WriteLine( " PatternStartDate: " + recurrencePattern.PatternStartDate );
					Debug.WriteLine( " PatternEndDate: " + recurrencePattern.PatternEndDate );

					Debug.WriteLine( " Duration: " + recurrencePattern.Duration );
					Debug.WriteLine( " DayOfMonth: " + recurrencePattern.DayOfMonth );
					Debug.WriteLine( " DayOfWeekMask: " + recurrencePattern.DayOfWeekMask );
					Debug.WriteLine( " EndTime: " + recurrencePattern.EndTime );
					Debug.WriteLine( "" );

					ListViewItem lvi = new ListViewItem( new string[] { 
					olAppt.Subject, 
					olAppt.Start.ToString(), 
					olAppt.End.ToString(),
					Convert.ToString( olAppt.AllDayEvent ), 
					recurrencePattern.RecurrenceType.ToString(),
					recurrencePattern.PatternStartDate.ToString(),
					recurrencePattern.PatternEndDate.ToString(),
					} );
					lvOutlookItems.Items.Add( lvi );

					EventEntry entry = new EventEntry( olAppt.Subject.ToString() );
					entry.Times.Add( new When( olAppt.Start, olAppt.End, olAppt.AllDayEvent ) );
					AtomEntry insertedEntry = service.Insert( new Uri( calendarUri ), entry ); 
					}

				olAppt = (Outlook.AppointmentItem)olItems.GetNext();
				}
#endif
			}

		private static readonly byte[] s_entropy = new byte[] { 9, 3, 7, 2, 1, 3, 8, 7, 7 };
		private static void storeLoginToken( string s )
			{
			UnicodeEncoding enc = new UnicodeEncoding();

			Settings.Default.credentialsToken = Convert.ToBase64String( ProtectedData.Protect( enc.GetBytes( s ), null, DataProtectionScope.CurrentUser ) );
			Settings.Default.Save();
			}

		private static string getLoginToken()
			{
			if ( String.IsNullOrWhiteSpace( Settings.Default.credentialsToken ) )
				return null;

			UnicodeEncoding enc = new UnicodeEncoding();

			return enc.GetString( ProtectedData.Unprotect( Convert.FromBase64String( Settings.Default.credentialsToken ), null, DataProtectionScope.CurrentUser ) );
			}
		}
	}
